package yui.comn.mybatisx.core.mapper;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Param;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;

import yui.comn.mybatisx.core.conditions.Wrapper;
import yui.comn.mybatisx.core.toolkit.EntityUtils;
import yui.comn.mybatisx.core.toolkit.SoftConstants;

/**
 * <p>
 * Mapper 继承该接口后，无需编写 mapper.xml 文件，即可获得CRUD功能
 * </p>
 * <p>
 * 这个 Mapper 支持 id 泛型
 * </p>
 *
 * @author yuyi (1060771195@qq.com)
 */
@SuppressWarnings("unchecked")
public interface BaseDao<T, D> {

    /**
     * <p>
     * 插入一条记录
     * </p>
     *
     * @param entity 实体对象
     */
    int insert(T entity);
    
    /**
     * <p>
     * 批量插入记录
     * </p>
     *
     * @param coll 实体对象列表
     */
    int insertBatch(@Param(SoftConstants.COLL) Collection<T> coll);

    /**
     * <p>
     * 根据 ID 修改全部的
     * </p>
     *
     * @param entity 实体对象
     */
    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 ID 批量修改有值的
     * </p>
     *
     * @param entity 实体对象
     */
    int updateBatchById(@Param(SoftConstants.COLL) Collection<T> coll);
    
    /**
     * <p>
     * 根据 ID 批量修改有值的
     * </p>
     *
     * @param entity 实体对象
     */
    default int updateBatchByDtoId(Collection<D> coll) {
        return updateBatchById((Collection<T>) EntityUtils.listVo(coll));
    }
    
    /**
     * <p>
     * 根据ID 修改所有值
     * </p>
     *
     * @param coll 实体对象列表
     */
    int updateById(@Param(Constants.ENTITY) T entity);
    
    /**
     * <p>
     * 根据 ID 批量修改所有值
     * </p>
     *
     * @param entity 实体对象
     */
    int updateAllBatchById(@Param(SoftConstants.COLL) Collection<T> coll);
    
    /**
     * <p>
     * 根据 ID 批量修改所有值
     * </p>
     *
     * @param entity 实体对象
     */
    default int updateAllBatchByDtoId(Collection<D> collection) {
        return updateAllBatchById((Collection<T>) EntityUtils.listVo(collection));
    }
    
    /**
     * <p>
     * 根据 ID 修改所有值
     * </p>
     *
     * @param entity 实体对象
     */
    int updateAllById(@Param(Constants.ENTITY) T entity);

    /**
     * 根据 entity 强制删除记录
     *
     * @param queryWrapper 实体对象封装操作类（可以为 null,里面的 entity 用于生成 where 语句）
     */
    int defunct(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * 根据 entity 条件，删除记录
     *
     * @param queryWrapper 实体对象封装操作类（可以为 null,里面的 entity 用于生成 where 语句）
     */
    int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 ID 删除
     * </p>
     *
     * @param id 主键ID
     */
    int deleteById(Serializable id);
    
    /**
     * 根据 columnMap 条件，删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    
    /**
     * <p>
     * 根据 对象ID 删除
     * </p>
     *
     * @param id 主键ID
     */
    default int deleteByVo(T vo) {
        return deleteById(EntityUtils.getPrimaryKeyValueByVo(vo));
    }
    
    /**
     * <p>
     * 根据 对象ID 删除
     * </p>
     *
     * @param id 主键ID
     */
    default int deleteByDto(D dto) {
        return deleteById(EntityUtils.getPrimaryKeyValueByDto(dto));
    }

    /**
     * <p>
     * 删除（根据ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    
    /**
     * <p>
     * 删除（根据对象ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    default int deleteBatchVoIds(Collection<T> voList) {
        return deleteBatchIds(EntityUtils.listPrimaryKeyValueByVos(voList));
    }
    
    /**
     * <p>
     * 删除（根据对象ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    default int deleteBatchDtoIds(Collection<D> dtoList) {
        return deleteBatchIds(EntityUtils.listPrimaryKeyValueByDtos(dtoList));
    }
    
    /**
     * <p>
     * 根据 ID 查询
     * </p>
     *
     * @param id 主键ID
     */
    D getById(Serializable id);
    
    /**
     * <p>
     * 根据 ID 查询
     * </p>
     *
     * @param id 主键ID
     */
    default T getVoById(Serializable id) {
        return (T) EntityUtils.getVo(getById(id));
    }
    
    /**
     * <p>
     * 根据 entity 条件，查询一条记录
     * </p>
     *
     * @param wrapper 实体对象
     */
    D get(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 entity 条件，查询一条记录
     * </p>
     *
     * @param wrapper 实体对象
     */
    default T getVo(@Param(Constants.WRAPPER) Wrapper<T> wrapper) {
		return (T) EntityUtils.getVo(get(wrapper));
    }
    
    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    D getByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    
    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    default T getVoByMap(Map<String, Object> columnMap) {
        return (T) EntityUtils.getVo(getByMap(columnMap));
    }
    
    /**
     * <p>
     * 根据字段条件，查询一条记录
     * </p>
     *
     * @param colomns 多个列逗号隔开
     * @param value 多个值对应多个colomn
     */
    default D get(String colomns, Object... values) {
        return getByMap(EntityUtils.getMap(colomns, values));
    }
    
    /**
     * <p>
     * 根据字段条件，查询一条记录
     * </p>
     *
     * @param colomns 多个列逗号隔开
     * @param value 多个值对应多个colomn
     */
    default T getVo(String colomns, Object... values) {
        return (T) EntityUtils.getVo(get(colomns, values));    
    }
    
    /**
     * <p>
     * 根据 Wrapper 条件，查询总记录数
     * </p>
     *
     * @param wrapper 实体对象
     */
    int count(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    List<D> list(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    default List<T> listVo(@Param(Constants.WRAPPER) Wrapper<T> wrapper) {
        return (List<T>) EntityUtils.listVo(list(wrapper));
    }
    
    /**
     * <p>
     * 查询（根据ID 批量查询）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    List<D> listBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    
    /**
     * <p>
     * 查询（根据ID 批量查询）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    default List<T> listVoBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList) {
        return (List<T>) EntityUtils.listVo(listBatchIds(idList));
    }

    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    List<D> listByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    
    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    default List<T> listVoByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap) {
        return (List<T>) EntityUtils.listVo(listByMap(columnMap));
    }
    
    /**
     * <p>
     * 根据字段条件，查询全部记录
     * </p>
     *
     * @param entityList 实体对象集合
     */
    default List<D> list(String colomns, Object... values) {
        return listByMap(EntityUtils.getMap(colomns, values));
    }
    
    /**
     * <p>
     * 根据字段条件，查询全部记录
     * </p>
     *
     * @param entityList 实体对象集合
     */
    default List<T> listVo(String colomns, Object... values) {
        return (List<T>) EntityUtils.listVo(list(colomns, values));
    }

    /**
     * <p>
     * 根据 Wrapper 条件，查询全部记录
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    List<Map<String, Object>> listMaps(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 columnMap 条件，查询全部记录
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    List<Map<String, Object>> listMapsByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    /**
     * <p>
     * 根据 Wrapper 条件，查询全部记录
     * 注意： 只返回第一个字段的值
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    List<Object> listObjs(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

    /**
     * <p>
     * 根据 entity 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param page         分页查询条件（可以为 RowBounds.DEFAULT）
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    <E extends IPage<D>> E page(E page, @Param(Constants.WRAPPER) Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param page         分页查询条件（可以为 RowBounds.DEFAULT）
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    default <E extends IPage<T>> E pageVo(IPage<D> page, @Param(Constants.WRAPPER) Wrapper<T> wrapper) {
        return (E) EntityUtils.pageVo(page(page, wrapper));
    }

    /**
     * <p>
     * 根据 Wrapper 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param page         分页查询条件
     * @param wrapper 实体对象封装操作类
     */
    <E extends IPage<Map<String, Object>>> E pageMaps(E page, @Param(Constants.WRAPPER) Wrapper<T> wrapper);
}
